﻿/* Autor: Achim Schnell */

using System;
using System.Reflection;

namespace AppFx.Reflection.Attributes
{
	/// <summary>
	/// Vereinfacht das Auslesen von Attributwerten
	/// </summary>
	public static class AttributeHelper
	{
		#region Methods

		/// <summary>
		/// Gibt zurück, ob ein oder mehrere Attrribute des angegebenen Typs verwendet wurden.
		/// </summary>
		/// <typeparam name="Tattribute">Der Typ des Attributs, nach welchem gesucht werden soll.</typeparam>
		/// <param name="propertyInfo">Die Informationen zur Eigenschaft.</param>
		/// <param name="attributeValues">Ein Array von Tattribute, in welchem gefundene Attribute gespeichert werden - NULL wenn das Attribut nicht verwendet wurde.</param>
		/// <param name="inherit">Wenn <c>true</c> dann wird auch nach geerbten Attributen gesucht.</param>
		/// <returns>
		///   <c>true</c> wenn ein oder mehrere Attribute des angegebenen Typs verwendet wurden, andernfalls <c>false</c>.
		/// </returns>
		/// <exception cref="T:System.ArgumentNullException">Wird geworfen, wenn 'propertyInfo' NULL ist.</exception>
		public static bool IsAttributeUsed<Tattribute>(PropertyInfo propertyInfo, ref Tattribute[] attributeValues, bool inherit = true) where Tattribute : class
		{
			if (propertyInfo == null)
				throw new ArgumentNullException("propertyInfo");
			object[] values = propertyInfo.GetCustomAttributes(typeof(Tattribute), inherit);
			System.Diagnostics.Debug.Assert(values != null);
			if (values.Length > 0)
			{
				attributeValues = (Tattribute[])values;
				return true;
			}
			else
			{
				return false;
			}
		}

		/// <summary>
		/// Gibt den Attribut-Wert zurück.
		/// </summary>
		/// <typeparam name="Treturn">Der Typ des Werts, der zurück gegeben werden soll.</typeparam>
		/// <param name="value">Der Wert, dessen Eigenschaft ausgelesen werden soll.</param>
		/// <param name="propertyName">Der Name der Eigenschaft die ausgelesen werden soll.</param>
		/// <returns></returns>
		/// <exception cref="T:System.ArgumentNullException">Wird geworfen, wenn 'propertyInfo' oder 'value' NULL ist.</exception>
		/// <exception cref="T:System.MissingMemberException">Wird geworfen, wenn 'value' über keine passende Eigenschaft verfügt.</exception>
		public static Treturn GetAttributeValue<Treturn>(object value, string propertyName)
		{
			if (propertyName == null || String.IsNullOrWhiteSpace(propertyName))
				throw new ArgumentNullException("propertyName");
			if (value == null)
				throw new ArgumentNullException("value");
			PropertyInfo attributePropertyInfo = value.GetType().GetProperty(propertyName);
			if (attributePropertyInfo == null)
				throw new MissingMemberException(value.GetType().Name, propertyName);
			return (Treturn)attributePropertyInfo.GetValue(value, null);
		}

		/// <summary>
		/// Liest den Wert des DescriptionAttributes aus.
		/// </summary>
		/// <param name="value">Enum-Wert.</param>
		/// <returns>Den Wert des DescriptionAttributes oder NULL.</returns>
		public static string GetEnumDescription(Enum value)
		{
			if (value == null)
				throw new ArgumentNullException("value");
			Type type = value.GetType();

			MemberInfo[] memInfo = type.GetMember(value.ToString());

			if (memInfo != null && memInfo.Length > 0)
			{
				object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);

				if (attrs != null && attrs.Length > 0)
				{
					return ((System.ComponentModel.DescriptionAttribute)attrs[0]).Description;
				}
			}

			return value.ToString();

		}

		#endregion
	}
}
